/***************************************************
> Copyright (C) 2024 ==KINGYI== All rights reserved.
> File Name: server.c
> Author:cjy
> Mail: 
> Created Time: 2024年08月15日 星期四 11时21分58秒
***************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>

#define MAX_EVENTS 10

typedef struct user_info{

    int id;
    char name[10];

} USE;

int main(int argc, const char* argv[])
{
    int sock = 0;
    int listen_sock = 0;
    int ret = 0;
    USE buf = {0}; // 初始化结构体

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == -1) {
        perror("sock");
        exit(-1);
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(6666);
    addr.sin_addr.s_addr = inet_addr("192.168.198.128");

    ret = bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
    if (ret == -1) {
        perror("bind");
        exit(-1);
    }

    listen(sock, 5);

    // 定义事件结构体和数组
    struct epoll_event ev;
    struct epoll_event events[MAX_EVENTS];

    // 定义监听套接字、连接套接字、文件描述符数量、epoll 文件描述符
    int conn_sock, nfds, epollfd;

    // 创建 epoll 实例
    epollfd = epoll_create1(0);

    if (epollfd == -1) {
        perror("epoll_create1");
        exit(EXIT_FAILURE);
    }
    
    // 初始化 epoll 事件结构体
    ev.events = EPOLLIN; // 设置读就绪事件
    ev.data.fd = sock;   // 关联监听套接字
    
    // 将监听套接字添加到 epoll 中进行监控
    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sock, &ev) == -1) {
        perror("epoll_ctl: listen_sock");
        exit(EXIT_FAILURE);
    }

    while (1) {
        nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); // 获取就绪事件
        if (nfds == -1) {
            perror("epoll_wait");
            exit(EXIT_FAILURE);
        }

        for (int n = 0; n < nfds; ++n) {
            if (events[n].data.fd == sock) { // 如果当前事件是监听套接字上的事件
                conn_sock = accept(sock, NULL, NULL);
                if (conn_sock == -1) {
                    perror("accept");
                    exit(EXIT_FAILURE);
                }

                ev.events = EPOLLIN; // 设置读就绪事件
                ev.data.fd = conn_sock; // 关联连接套接字
                if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn_sock, &ev) == -1) {
                    perror("epoll_ctl: conn_sock");
                    exit(EXIT_FAILURE);
                }
            } else {
                ret = recv(events[n].data.fd, &buf, sizeof(buf), 0);
                if (ret == -1) {
                    perror("recv");
                    exit(-1);
                }

                printf("id is %d\n", buf.id);
                printf("name is %s\n", buf.name);

                ret = send(events[n].data.fd, &buf, sizeof(buf), 0);
                if (ret == -1) {
                    perror("send");
                    exit(-1);
                }
            }
        }
    }

    close(sock);
    close(epollfd);

    return 0;
}

